/*
(c) Copyright 2011 Telefonica, I+D. Printed in Spain (Europe). All Righ
Reserved.
The copyright to the software program(s) is property of Telefonica I+D.
The program(s) may be used and or copied only with the express written
consent of Telefonica I+D or in accordance with the terms and conditions
stipulated in the agreement/contract under which the program(s) have
been supplied.
*/
package com.telefonica.claudia.smi;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
import javax.persistence.spi.PersistenceProvider;
import org.apache.log4j.Logger;
import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Directory;
import org.restlet.Restlet;
import org.restlet.Router;
import org.restlet.data.Protocol;
import com.telefonica.claudia.smi.console.ConsoleApplication;
import com.telefonica.claudia.smi.deployment.DeploymentApplication;
import com.telefonica.claudia.smi.monitoring.MonitoringApplication;
import com.telefonica.claudia.smi.provisioning.ProvisioningApplication;
import com.telefonica.claudia.smi.task.TaskApplication;
import com.telefonica.claudia.smi.task.TaskManager;
import com.telefonica.claudia.smi.templateManagement.TemplateManagementApplication;
public class Main {
protected static final Set<PersistenceProvider> providers = new HashSet<PersistenceProvider>();
private static final int ERROR_CODE_INITIALIZATION = 1;
private static final int ERROR_CODE_DRIVERS = 2;
public static final String PATH_TO_PROPERTIES_FILE = "./conf/tcloud.properties";
public static final String PATH_TO_REPOSITORY = "./repository";
private static final String KEY_PORT = "com.telefonica.claudia.server.port";
private static final String KEY_HOST = "com.telefonica.claudia.server.host";
private static final String KEY_DRIVER_PROVISIONING = "com.telefonica.claudia.smi.drivers.provisioning";
private static final String KEY_DRIVER_DEPLOYMENT = "com.telefonica.claudia.smi.drivers.deployment";
private static final String KEY_DRIVER_MONITORING = "com.telefonica.claudia.smi.drivers.monitoring";
private static final String KEY_DRIVER_TASKMANAGER = "com.telefonica.claudia.smi.drivers.taskManager";
private static final String KEY_DRIVER_TEMPLATEMANAGEMENT = "com.telefonica.claudia.smi.drivers.templateManagement";
private static final String KEY_DRIVER_CONSOLE = "com.telefonica.claudia.smi.drivers.console";
public static final Object CUSTOMIZATION_PORT_PROPERTY = "com.telefonica.claudia.customization.port";
public static final String PROTOCOL = "http://";
private static final String HEARTBEAT_URI = "/heartbeat";
private static Logger log = Logger
.getLogger("com.telefonica.claudia.smi.Main");
public static int serverPort;
public static String serverHost;
/**
* Load all the drivers deployed in the folder /driver under the root of the
* application. This folder is created during the deployment.
*
* The driver folder should contain a collection of folders, each one
* belonging to a different driver. This folder should contain the all the
* jar files needed to execute the driver, including its dependencies.
*
* Even if more than one driver is found in the driver folder, only the one
* specified in the config file will be loaded.
*
* @return A class loader with all the jars belonging to the drivers loaded.
*
* @throws MalformedURLException
*/
private static URLClassLoader loadDrivers() throws MalformedURLException {
// First of all, check if there is any zip file, and uncompress it
unzipFiles();
// Load all the drivers from the path
File driverFolder = new File("driver");
File[] driverFolders = driverFolder.listFiles();
ArrayList<URL> urlDrivers = new ArrayList<URL>();
for (File particularDriverFolder : driverFolders) {
if (particularDriverFolder.getName().charAt(0) == '.'
|| !particularDriverFolder.isDirectory()) {
log.info("Ignoring [" + particularDriverFolder.getName() + "]");
continue;
}
File[] drivers = particularDriverFolder.listFiles();
log.info("Examining [" + particularDriverFolder.getName()
+ "] driver folder");
for (int i = 0; i < drivers.length; i++) {
if (!drivers[i].getName().matches(".*jar")) {
log.info("Ignoring [" + drivers[i].getName() + "]");
continue;
}
// urlDrivers.add(new URL("jar:file://" +
// drivers[i].getAbsolutePath() + "!/"));
urlDrivers.add(drivers[i].toURL());
log.info("Adding [" + drivers[i].getName()
+ "] to the classpath");
}
}
return new URLClassLoader(urlDrivers
.toArray(new URL[urlDrivers.size()]));
}
public static void unzipFiles() {
File driverFolder = new File("driver");
File[] driverFolders = driverFolder.listFiles();
for (File particularDriverFile : driverFolders) {
// Check if its a zip file. If it is, unzip it and delete it.
if (particularDriverFile.getName().matches(".*\\.zip")) {
String fileName = particularDriverFile.getName();
log.info("Trying to uncompress: " + fileName);
File targetDir = new File(driverFolder, fileName.substring(0,
fileName.indexOf(".zip")));
if (!targetDir.mkdir()) {
log.warn("The directory for driver " + fileName
+ " could not be created. Ignoring driver.");
continue;
}
try {
ZipFile zipFile = new ZipFile(particularDriverFile);
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
// Create the file inside the target directory
if (entry.getName().endsWith(".jar")){
File newEntry = new File(targetDir, entry.getName());
FileOutputStream out = new FileOutputStream(newEntry);
InputStream in = zipFile.getInputStream(entry);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) >= 0)
out.write(buffer, 0, len);
in.close();
out.close();
}
}
if (!particularDriverFile.delete())
log.warn("The file " + particularDriverFile.getName()
+ " could not be deleted.");
} catch (ZipException e) {
log.warn("The file could not be uncompressed. Zip error: "
+ e.getMessage());
} catch (IOException e) {
log
.warn("The file could not be uncompressed. Unknown IO Error: "
+ e.getMessage());
}
}
}
}
public static void main(String[] args) throws Exception {
// Load the configuration file
Map <String, Object> configuration = new HashMap<String, Object>();
configuration.put("hibernate.connection.url", "jdbc:mysql://62.217.120.136:3306/monitoring?noDatetimeStringSync=true");
configuration.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
configuration.put("hibernate.connection.username", "claudia");
configuration.put("hibernate.connection.password", "ClaudiaPass");
configuration.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
configuration.put("hibernate.c3p0.min_size", "5");
configuration.put("hibernate.c3p0.max_size", "50");
configuration.put("hibernate.c3p0.timeout", "5000");
configuration.put("hibernate.c3p0.max_statements", "100");
createEntityManagerFactory("ClaudiaPU",configuration);
Properties prop = new Properties();
prop.load(new FileInputStream(PATH_TO_PROPERTIES_FILE));
try {
serverPort = Integer.parseInt(prop.getProperty(KEY_PORT));
} catch (NumberFormatException nfe) {
log.error("Error parsing the " + KEY_PORT
+ " property. A number was expected, but '"
+ prop.getProperty(KEY_PORT) + "' was found.");
System.exit(ERROR_CODE_INITIALIZATION);
}
serverHost = prop.getProperty(KEY_HOST);
// Load the appropiate drivers
URLClassLoader cl = loadDrivers();
// Create a new Component.
Component component = new Component();
// Add a new HTTP server listening on port.
component.getServers().add(Protocol.HTTP, serverPort);
TaskApplication taskApp = new TaskApplication();
component.getDefaultHost().attach(taskApp);
((Router)taskApp.getRoot()).attach(HEARTBEAT_URI , HeartbeatResource.class);
// Load the driver for TaskManager
if (prop.get(KEY_DRIVER_TASKMANAGER) != null
&& !prop.get(KEY_DRIVER_TASKMANAGER).equals("")) {
try {
Class classDriver = cl.loadClass(prop
.getProperty(KEY_DRIVER_TASKMANAGER));
// Initialize the Task Manager
TaskManager taskManager = TaskApplication.setDriver(classDriver, prop);
taskManager.createManager(taskManager);
log.info("TaskManager active.");
} catch (IllegalArgumentException iae) {
log.error("Driver didn't extend the expected class.");
System.exit(ERROR_CODE_DRIVERS);
} catch (ClassNotFoundException cnfe) {
log.error("The TaksManager class was not loaded. Check the driver folder contents.");
System.out.println("The TaksManager class was not loaded. Check the driver folder contents.");
System.exit(ERROR_CODE_DRIVERS);
}
} else {
log.error("No TaskManager driver was specified. Task driver is mandatory.");
System.out.println("No TaskManager driver was specified. Task driver is mandatory.");
System.exit(ERROR_CODE_DRIVERS);
}
// Load the driver for each API
if (prop.get(KEY_DRIVER_MONITORING) != null
&& !prop.get(KEY_DRIVER_MONITORING).equals("")) {
try {
Class classDriver = cl.loadClass(prop
.getProperty(KEY_DRIVER_MONITORING));
/*
* Properties prop = new Properties(); try { prop.load(new
* FileInputStream("./conf/tcloud.properties")); } catch
* (FileNotFoundException e1) { // TODO Auto-generated catch block
* e1.printStackTrace(); } catch (IOException e1) { // TODO
* Auto-generated catch block e1.printStackTrace(); }
*/
/* for (String s : names) {
try{
providers.add((PersistenceProvider)loader.loadClass(s).newInstance());
} catch (ClassNotFoundException exc){
} catch (InstantiationException exc){
} catch (IllegalAccessException exc){
}*/
MonitoringApplication.setDriver(classDriver, prop);
MonitoringApplication app = new MonitoringApplication();
app.modifyRoot((Router) taskApp.getRoot());
log.info("Monitoring application active.");
} catch (IllegalArgumentException iae) {
log.error("Driver didn't extend the expected class.");
} catch (ClassNotFoundException cnfe) {
log
.error("The Monitoring class was not loaded. Check the driver folder contents.");
System.out
.println("The Monitoring class was not loaded. Check the driver folder contents.");
System.exit(ERROR_CODE_DRIVERS);
}
}
if (prop.get(KEY_DRIVER_DEPLOYMENT) != null
&& !prop.get(KEY_DRIVER_DEPLOYMENT).equals("")) {
try {
Class classDriver = cl.loadClass(prop
.getProperty(KEY_DRIVER_DEPLOYMENT));
DeploymentApplication.setDriver(classDriver, prop);
DeploymentApplication app = new DeploymentApplication();
app.modifyRoot((Router) taskApp.getRoot());
log.info("Deployment application active.");
} catch (IllegalArgumentException iae) {
log.error("Driver didn't extend the expected class.");
} catch (ClassNotFoundException cnfe) {
log
.error("The Deployment class was not loaded. Check the driver folder contents.");
System.out
.println("The Deployment class was not loaded. Check the driver folder contents.");
System.exit(ERROR_CODE_DRIVERS);
}
}
if (prop.get(KEY_DRIVER_PROVISIONING) != null
&& !prop.get(KEY_DRIVER_PROVISIONING).equals("")) {
try {
Class classDriver = cl.loadClass(prop.getProperty(KEY_DRIVER_PROVISIONING));
ProvisioningApplication.setDriver(classDriver, prop);
ProvisioningApplication app = new ProvisioningApplication();
app.modifyRoot((Router) taskApp.getRoot());
log.info("Provisioning application active.");
} catch (IllegalArgumentException iae) {
log.error("Driver didn't extend the expected class.");
} catch (ClassNotFoundException cnfe) {
log
.error("The Provisioning driver class was not loaded. Check the driver folder contents.");
System.out
.println("The Provisioning driver class was not loaded. Check the driver folder contents.");
System.exit(ERROR_CODE_DRIVERS);
}
}
if (prop.get(KEY_DRIVER_TEMPLATEMANAGEMENT) != null
&& !prop.get(KEY_DRIVER_TEMPLATEMANAGEMENT).equals("")) {
try {
Class classDriver = cl.loadClass(prop.getProperty(KEY_DRIVER_TEMPLATEMANAGEMENT));
TemplateManagementApplication.setDriver(classDriver, prop);
TemplateManagementApplication app = new TemplateManagementApplication();
app.modifyRoot((Router) taskApp.getRoot());
log.info("TemplateManagement application active.");
} catch (IllegalArgumentException iae) {
log.error("Driver didn't extend the expected class.");
} catch (ClassNotFoundException cnfe) {
log.error("The Template Manager driver class was not loaded. Check the driver folder contents.");
System.out.println("The Template Manager class was not loaded. Check the driver folder contents.");
System.exit(ERROR_CODE_DRIVERS);
}
}
if (prop.get(KEY_DRIVER_CONSOLE) != null
&& !prop.get(KEY_DRIVER_CONSOLE).equals("")) {
try {
Class classDriver = cl.loadClass(prop.getProperty(KEY_DRIVER_CONSOLE));
ConsoleApplication.setDriver(classDriver, prop);
ConsoleApplication app = new ConsoleApplication();
app.modifyRoot((Router) taskApp.getRoot());
log.info("Console application active.");
} catch (IllegalArgumentException iae) {
log.error("Driver didn't extend the expected class.");
} catch (ClassNotFoundException cnfe) {
log.error("The Console driver class was not loaded. Check the driver folder contents.");
System.out.println("The Console driver class was not loaded. Check the driver folder contents.");
System.exit(ERROR_CODE_DRIVERS);
}
}
final String staticDocRoot = prop.getProperty("com.telefonica.claudia.server.docroot");
if (staticDocRoot != null && staticDocRoot.trim().equals("") == false) {
// start serving static files
// @see http://www.restlet.org/documentation/1.1/tutorial#part06
Application application = new Application(component.getContext().createChildContext()) {
@Override
public Restlet createRoot() {
return new Directory(getContext(), staticDocRoot);
}
};
((Router)taskApp.getRoot()).attach("", application);
}
// Start the component.
component.getDefaultHost().attach(taskApp);
component.start();
log.info("Service started");
}
private static void findAllProviders() throws IOException {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Enumeration<URL> resources =
loader.getResources("META-INF/services/" + PersistenceProvider.class.getName());
Set<String> names = new HashSet<String>();
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
InputStream is = url.openStream();
try {
names.addAll(providerNamesFromReader(new BufferedReader(new InputStreamReader(is))));
} finally {
is.close();
}
}
for (String s : names) {
try{
providers.add((PersistenceProvider)loader.loadClass(s).newInstance());
System.out.println ("Provider " + s);
} catch (ClassNotFoundException exc){
} catch (InstantiationException exc){
} catch (IllegalAccessException exc){
}
}
}
private static final Pattern nonCommentPattern = Pattern.compile("^([^#]+)");
private static Set<String> providerNamesFromReader(BufferedReader reader) throws IOException {
Set<String> names = new HashSet<String>();
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
Matcher m = nonCommentPattern.matcher(line);
if (m.find()) {
names.add(m.group().trim());
}
}
return names;
}
public static EntityManagerFactory createEntityManagerFactory(
String persistenceUnitName, Map properties) {
EntityManagerFactory emf = null;
if (providers.size() == 0) {
try{
findAllProviders();
} catch (IOException exc){};
}
for (PersistenceProvider provider : providers) {
emf = provider.createEntityManagerFactory(persistenceUnitName, properties);
if (emf != null){
break;
}
}
if (emf == null) {
throw new PersistenceException("No Persistence provider for EntityManager named " + persistenceUnitName);
}
return emf;
}
}